﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Drawing2D;
using System.Diagnostics;

namespace Hue.UC {
	public partial class EyeDropper : Control {

		#region ..:: Declarations Members ::..

		private Bitmap _snapshot;
		private Bitmap _icon;
		private Bitmap _iconActive;
		private Color _selectedColor;
		private float _zoom = 4;

		private Point _iconPoint;

		bool _isCapturing = false;

		#endregion

		#region ..:: Public Properties ::..

		[Category("Eyedropper")]
		[DefaultValue(4)]
		public int Zoom {
			get { return (int)_zoom; }
			set {
				_zoom = value;
				RecalcSnapshotSize();
			}
		}

		[Category("Eyedropper")]
		[DefaultValue(typeof(Color), "Empty")]
		public Color SelectedColor {
			get { return _selectedColor; }
			set {
				if (_selectedColor == value)
					return;
			}
		}

		#endregion

		[Category("Color")]
		public event EventHandler<SelectedColorChangedEventArgs> SelectedColorChanged;
		private void OnSelectedColorChanged(Color e) {
			EventHandler<SelectedColorChangedEventArgs> handler = SelectedColorChanged;
			if (handler != null) {
				SelectedColorChanged(this, new SelectedColorChangedEventArgs(e));
			}
		}

		//public event EventHandler SelectedColorChanged;

		public EyeDropper() {
			InitializeComponent();

			this.DoubleBuffered = true;
			//m_icon = new Bitmap(typeof(EyedropColorPicker), "Resources.eyedropper.bmp");
			//m_icon.MakeTransparent(Color.Magenta);
			_iconPoint = new Point();
			_icon = Properties.Resources.eyeDrop;
			_iconActive = Properties.Resources.eyeDropActive;
		}

		//protected override void OnPaint(PaintEventArgs pe) {
		//   base.OnPaint(pe);
		//}

		RectangleF ImageRect {
			get {
				return Util.Rect(ClientRectangle);
			}
		}

		private void RecalcSnapshotSize() {
			if (_snapshot != null)
				_snapshot.Dispose();
			RectangleF r = ImageRect;
			int w = (int)(Math.Floor(r.Width / Zoom));
			int h = (int)(Math.Floor(r.Height / Zoom));
			_snapshot = new Bitmap(w, h);
		}

		private void GetSnapshot() {
			Point p = Control.MousePosition;
			p.X -= _snapshot.Width / 2;
			p.Y -= _snapshot.Height / 2;

			using (Graphics dc = Graphics.FromImage(_snapshot)) {
				dc.CopyFromScreen(p, new Point(0, 0), _snapshot.Size);
				Refresh(); //Invalidate();

				PointF center = Util.Center(new RectangleF(0, 0, _snapshot.Size.Width, _snapshot.Size.Height));
				Color c = _snapshot.GetPixel((int)Math.Round(center.X), (int)Math.Round(center.Y));
				if (c != _selectedColor) {
					_selectedColor = c;
					if (SelectedColorChanged != null) {
						OnSelectedColorChanged(_selectedColor);
					}
				}
			}
		}

		protected override void OnResize(EventArgs e) {
			base.OnResize(e);
			_iconPoint.X = (this.Width / 2); // +(_icon.Width);
			_iconPoint.Y = (this.Height / 2) - (_icon.Height);

			RecalcSnapshotSize();
		}

		protected override void OnPreviewKeyDown(PreviewKeyDownEventArgs e) {
			base.OnPreviewKeyDown(e);
			switch (e.KeyCode) {
				case Keys.Up:
				case Keys.Right:
				case Keys.Down:
				case Keys.Left:
					e.IsInputKey = true;
					break;
			}
		}

		protected override void OnKeyDown(KeyEventArgs e) {
			base.OnKeyDown(e);
			if (_isCapturing) {
				Point p = Cursor.Position;
				switch (e.KeyCode) {
					case Keys.Right:
					case Keys.D:
						p.X++;
						break;
					case Keys.Left:
					case Keys.A:
						p.X--;
						break;
					case Keys.Down:
					case Keys.X:
						p.Y++;
						break;
					case Keys.Up:
					case Keys.W:
						p.Y--;
						break;
					case Keys.Space:
						if (e.Modifiers == Keys.Shift) {
							p.X--;
						} else {
							p.X++;
						}
						break;

				}
				Cursor.Position = p;
			}

		}

		//protected override void OnKeyPress(KeyPressEventArgs e) {
		//   base.OnKeyPress(e);
		//   Trace.WriteLine(e.KeyChar);
		//}

		protected override void OnMouseDown(MouseEventArgs e) {
			base.OnMouseDown(e);
			if ((e.Button & MouseButtons.Left) == MouseButtons.Left) {
				Cursor = Cursors.Cross;
				_isCapturing = true;
				Invalidate();
			}
		}

		protected override void OnMouseMove(MouseEventArgs e) {
			base.OnMouseMove(e);
			if ((e.Button & MouseButtons.Left) == MouseButtons.Left) {
				GetSnapshot();
			}
		}

		protected override void OnMouseUp(MouseEventArgs e) {
			base.OnMouseUp(e);
			{
				Cursor = Cursors.Arrow;
				_isCapturing = false;
				Invalidate();
			}
		}

		protected override void OnPaint(PaintEventArgs e) {
			base.OnPaint(e);

			Graphics g = e.Graphics;
			g.InterpolationMode = InterpolationMode.NearestNeighbor;
			g.PixelOffsetMode = PixelOffsetMode.Half;

			Rectangle rr = ClientRectangle;

			if (_snapshot != null) {
				g.InterpolationMode = InterpolationMode.NearestNeighbor;
				RectangleF r = RectangleF.Empty;
				r.Width = _snapshot.Size.Width * Zoom;
				r.Height = _snapshot.Size.Height * Zoom;
				r.X = 0;
				r.Y = 0;
				g.DrawImage(_snapshot, r);

				if (_isCapturing) {
					PointF center = Util.Center(r);
					Rectangle centerrect = new Rectangle(Util.Point(center), new Size(0, 0));
					centerrect.X -= ((int)Zoom / 2 - 1);
					centerrect.Y -= ((int)Zoom / 2 - 1);
					centerrect.Width = (int)Zoom;
					centerrect.Height = (int)Zoom;

					//g.DrawImage(_iconActive, _iconPoint.X - 2, _iconPoint.Y - 1);
					g.DrawImage(_iconActive, centerrect.Right, centerrect.Top - _icon.Height);
					//g.DrawRectangle(Pens.Black, centerrect);
				} else {
					//int offset = 3;
					//e.Graphics.FillRectangle(SystemBrushes.Control, new Rectangle(new Point(offset, offset), m_icon.Size));
					g.DrawImage(_icon, _iconPoint);

					//e.Graphics.DrawImage(_icon, offset, offset);


				}
			}


			Pen pen = new Pen(BackColor, 3);
			rr.Inflate(-1, -1);

			//g.DrawRectangle(pen, rr);
			Util.DrawFrame(g, rr, 6, Color.CadetBlue);
		}


	}


	public class SelectedColorChangedEventArgs : EventArgs {

		public Color SelectedColor { get; private set; }

		public SelectedColorChangedEventArgs(Color selectedColor) {
			this.SelectedColor = selectedColor;
		}

	}


}
